package cn.hh.ymcc.service.impl;

import cn.hh.ymcc.domain.CourseType;
import cn.hh.ymcc.mapper.CourseTypeMapper;
import cn.hh.ymcc.service.ICourseTypeService;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 课程目录 服务实现类
 * </p>
 *
 * @author huang.hao
 * @since 2025-04-23
 */
@Service
@Slf4j
public class CourseTypeServiceImpl extends ServiceImpl<CourseTypeMapper, CourseType> implements ICourseTypeService {

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    /**
    *    1.优先查询redis中有没有无限极树缓存
    *    2.有,直接返回
     *   3.没有,查询数据库,封装数据 放入redis缓存
     * @return
     */
    @Cacheable(cacheNames = "coursetype",key = "'tree'") //  coursetype::tree
    @Override
    public List<CourseType> treeData() {
        List<CourseType> tree = tree();
        return tree;
    }


    /**
     *  备份
     *   1.优先查询redis中有没有无限极树缓存
     *   2.有,直接返回
     *   3.没有,查询数据库,封装数据
     * @return
     */
    public List<CourseType> treeData2() {
        // 1.优先查询redis中有没有无限极树缓存
        // 1.1创建一个Key
        String courseTypeTreeKey = "coursetypetree";
        // 1.2.使用redis获取到Key,得到Key对象
        Object obj = redisTemplate.opsForValue().get(courseTypeTreeKey);
        if (obj != null){
            log.info("走redis查询返回");
            // 2.有,直接返回
            return (List<CourseType>) obj;
        }
        //  3.没有,查询数据库,封装数据 存入redis
        log.info("走mysql查询返回");
        List<CourseType> tree = tree();
        //  将tree存入redis中
        redisTemplate.opsForValue().set(courseTypeTreeKey,tree);
        return tree();
    }


    /**
     *  封装无限极树
     * @return
     */
    public List<CourseType> tree() {
        // 1.将所有数据全部查出来,放到内存
        List<CourseType> courseTypes = selectList(null); // 使用selectList方法查询所有,没有wrapper就传null,获取到所有数据对象

        // @TODO 改为stream
        HashMap<Long, CourseType> allTypes = new HashMap<>();
        courseTypes.forEach(type->{
            allTypes.put(type.getId(),type);
        });

        // 2.查找出顶级节点组成firstList --- 返回的List
        List<CourseType> firstList = new ArrayList<>(); // 创建一个空的List对象 firstList
        for(CourseType type:courseTypes){ // 遍历所有数据的List对象 courseTypes
            if (type.getPid() == null || type.getPid().intValue() == 0){ // 用遍历出的对象做比较,获取parentId == null 或者 parentId == 0,就是顶级  pid=数据类型是Long,使用intValue做比较
                firstList.add(type); // 将顶级转入到空的List中
            }else { // 不是第一层级
                allTypes.get(type.getPid()).getChildren().add(type);
                // 3.所有不是顶级的都找自己的上级,并把自己加入到上级的children
//                for (CourseType parent:courseTypes){ // 遍历所有数据的List对象 courseTypes
//                    if (parent.getId().longValue() == type.getPid().longValue()){ // 判断下级对象id是否 == 上级对象id, 如果自己id和上级id相同,说明找到了自己的上级对象
//                        parent.getChildren().add(type);  // 下级对象调用Children[List<CourseType>]无参构造,将自己装入到children的List集合中去
//                    }
//                }
            }
        }
        return firstList;
    }

    /**
     *  增加操作清除redis缓存
     * @param entity
     * @return
     */
    @Override
    @CacheEvict(cacheNames = "coursetype",key = "'tree'") //  coursetype::tree  删除缓存
    public boolean insert(CourseType entity) {
        boolean insert = super.insert(entity);
        return insert;
    }

    /**
     * 修改操作清除redis缓存
     * @param entity
     * @return
     */
    @Override
    @CacheEvict(cacheNames = "coursetype",key = "'tree'") //  coursetype::tree  删除缓存
    public boolean updateById(CourseType entity) {
        boolean update  = super.updateById(entity);

        return update;
    }

    /**
     *  删除操作清除redis缓存
     * @return
     */
    @Override
    @CacheEvict(cacheNames = "coursetype",key = "'tree'") //  coursetype::tree  删除缓存
    public boolean deleteById(Serializable id) {
        boolean deleteById = super.deleteById(id);
        return deleteById;
    }
}
